package me.ezitku.base.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
import android.widget.TextView
import com.ug_project.annotations.AvailableDefaultValue
import com.ug_project.objects.isNotNull
import com.ug_project.objects.isNull
import com.ug_project.views.FONT_NAME
import com.ug_project.views.font

/**
 * بۇ AutoCompleteTextView نىڭ Adapter سى
 * بۇنىڭ filter دىگەن فونكىسسيەسىلا ئارتۇق
 */
open class BaseAdapter<T>(val context: Context, val layout_res_id: Int, var data: ArrayList<T>?) : android.widget.BaseAdapter(), Filterable {
    private var filterData = ArrayList<T>()

    val arrayFilter by lazy {
        ArrayFilter()
    }

    override fun getFilter(): Filter {
        return arrayFilter
    }

    private var _getView: ((position: Int, itemView: View, parent: ViewGroup?, data: ArrayList<T>?) -> Unit)? = null
    private var _getItem: ((position: Int) -> Any)? = null
    private var _getItemId: ((position: Int) -> Long)? = null
    private var _getCount: (() -> Int)? = null
    private val _inflater: LayoutInflater = LayoutInflater.from(context)

    private var _filter: ((newText: String, data: T) -> Boolean)? = null

    open fun GetItem(getitem: (position: Int) -> Any) {
        _getItem = getitem
    }

    @AvailableDefaultValue
    open fun GetItemId(getitemid: (position: Int) -> Long) {
        _getItemId = getitemid
    }

    open fun GetCount(getcount: () -> Int) {
        _getCount = getcount
    }

    open fun GetView(getview: (position: Int, convertView: View, parent: ViewGroup?, data: ArrayList<T>?) -> Unit) {
        _getView = getview
    }

    open fun filter(filter: (newText: String, data: T) -> Boolean) {
        _filter = filter
    }


    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {

        _getView isNull {
            _Exception("GetView(getview: (position: Int, inflatedViews: Array<View>, convertView: View?, parent: ViewGroup?) -> View)")
        }

        val parent_view: View = convertView ?: try {
            _inflater.inflate(layout_res_id, null)
        } catch (exception: Exception) {
            throw Exception("پارامىتىر قىلىپ بەرگەن \n layout_res_id \n بولسا چوقۇم \n ViewGroup نىڭ ئۆزى ياكى بالىسى بولىشى كىرەك")
        }
//        when (parent_view) {
//            is ViewGroup -> {
//                parent_view.font = FONT_NAME
//            }
//            is TextView -> {
//                parent_view.font = FONT_NAME
//            }
//        }

        _getView!!(position, parent_view, parent, filterData)

        return parent_view
    }

    override fun getItem(position: Int): Any {
        var item: Any? = null
        data.isNull {
            _getItem.isNull {
                _Exception("GetItem(getitem: (position: Int)-> Any)")
            }
            item = _getItem!!(position)
        }
        data isNotNull {
            item = it[position]
        }
        return item!!
    }

    override fun getItemId(position: Int): Long {
        var id = position
        _getItemId isNotNull {
            id = _getItemId!!(position).toInt()
        }
        return id.toLong()
    }

    override fun getCount(): Int {
        var count = -1
        _getCount.isNull {
            count = filterData.size
        }
        _getCount.isNotNull {
            count = _getCount!!()
        }
        return count
    }

    private fun _Exception(message: String) {
        throw Exception("خاتالىق يۈز بەردى، بەزى فۇنكىسىيەلەرنى چوقۇم ئىشلىتىپ ئۇچۇرلارنى تولۇق تەمىنلىشىڭىز كىرەك ياكى \n\ndata\n\nارامىتىرىغا قىممەت بىرىپ ئىشلىتىدىغان سانلىق مەلۇماتنى دەسلەپلەشتۈرۈشىڭىز كىرەك،\n\nنۆۋەتتىكى ئەمەلگە ئاشۇرۇلمىغان فۇنكىسىيە:\n\n$message")
    }

    inner class ArrayFilter : Filter() {

        override fun performFiltering(constraint: CharSequence?): FilterResults {
            var filterResult = FilterResults()
            if (constraint == null || constraint.isEmpty()) {
                filterResult.values = data
                filterResult.count = data?.size ?: 0
            } else {
                var result = data?.filter { _filter!!(constraint.toString(), it) }?:ArrayList()
                filterResult.values = result
                filterResult.count = result.size
//                print("$constraint")
            }
            return filterResult
        }

        override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
            if (results != null && results.count > 0) {
                filterData.clear()
                filterData.addAll(results.values as ArrayList<T>)
                notifyDataSetChanged()
            } else {
                notifyDataSetInvalidated()
            }
        }

    }

}

fun <T> createListAdapter(context: Context, layout_res_id: Int, data: ArrayList<T>, constructor: BaseAdapter<T>.() -> Unit): BaseAdapter<T> {
    var temp = BaseAdapter(context, layout_res_id, data)
    temp.constructor()
    return temp
}

fun <T> Context.createAutoCompleteAdapter(layout_res_id: Int, data: ArrayList<T>, constructor: BaseAdapter<T>.() -> Unit): BaseAdapter<T> {
    var temp = BaseAdapter(this, layout_res_id, data)
    temp.constructor()
    return temp
}




